#include "tcpclient.h"
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <arpa/inet.h>
#include <cerrno>
#include <fcntl.h>
TcpClient::TcpClient() : sockfd(-1), isConnected(false) {}
TcpClient::~TcpClient() 
{
    disconnect();
}
//链接服务器
bool TcpClient::connectToServer(const std::string& ip, int port) 
{
    //创建客户端套接字
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd < 0) 
    {
        std::cerr << "创建socket失败" << std::endl;
        return false;
    }
    // 配置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    //判断是不是正常ip
    if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) 
    {
        std::cerr << "无效的IP地址" << std::endl;
        close(sockfd);
        return false;
    }
    // 连接服务器
    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) 
    {
        std::cerr << "连接服务器失败" << std::endl;
        close(sockfd);
        return false;
    }
    // 连接服务器成功后，设置接收超时为 3 秒
    struct timeval timeout;
    timeout.tv_sec = 3;    
    timeout.tv_usec = 0;   
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) 
    {
        std::cerr << "设置接收超时失败：" << strerror(errno) << std::endl;
        close(sockfd);
        return false;
    }
    isConnected = true;
    //启动线程循环接收线程
    // recvThread = std::thread(&TcpClient::receiveLoop, this);//可以访问当前函数所有的成员变量
    return true; 
}

// 新增一个启动接收线程的函数（供角色协商后调用）
void TcpClient::startRecvThread() 
{
    if (isConnected && !recvThread.joinable()) 
    {
        recvThread = std::thread(&TcpClient::receiveLoop, this);
    }
}
//线程接收数据
void TcpClient::receiveLoop() 
{
    char buffer[1024];
    while (isConnected) 
    {
        ssize_t len = recv(sockfd, buffer, sizeof(buffer) - 1, 0);

        if (len > 0) 
        {
            buffer[len] = '\0';
            std::lock_guard<std::mutex> lock(mtx);
            recvBuffer = std::string(buffer, len);  // 确保完整复制数据
            std::cout << "接收到数据: " << recvBuffer << std::endl;
        }
        else if (len == 0) 
        {
            std::cerr << "对方已断开连接" << std::endl;
            isConnected = false;
            break;
        }
        else 
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK) 
            {
                // 非阻塞模式下没有数据是正常的，短暂休眠
                usleep(10000); // 10ms
                continue;
            }
            else 
            {
                std::cerr << "接收错误：" << strerror(errno) << "，连接断开" << std::endl;
                isConnected = false;
                break;
            }
        }
    }
    std::cout << "接收线程已退出" << std::endl;  // 改为正常输出，便于调试
}

//发送数据
bool TcpClient::sendData(const std::string& data) 
{
    if (!isConnected) 
        return false;
    return send(sockfd, data.c_str(), data.size(), 0) > 0;
}

//接收读取到的数据
std::string TcpClient::getReceivedData() 
{
    std::lock_guard<std::mutex> lock(mtx);//避免边接收边读取造成读取不完整
    std::string data = recvBuffer;
    recvBuffer.clear();  // 读取后清空缓冲区
    return data;
}

//清空缓冲区
void TcpClient::clearBuffer() 
{
    std::lock_guard<std::mutex> lock(mtx);
    recvBuffer.clear();
}

//如果断开链接就清除套接字
void TcpClient::disconnect() 
{
    if (isConnected) 
    {
        isConnected = false;
        close(sockfd);
        if (recvThread.joinable()) 
        {
            recvThread.join();
        }
    }
}

//直接接收数据到缓冲区（供角色协商阶段使用）
ssize_t TcpClient::recvData(char* buffer, size_t len) 
{
        if (!isConnectedStatus()) return -1;
        return recv(sockfd, buffer, len, 0);  // 内部访问私有 sockfd
}
#include <fcntl.h>  // 用于 fcntl 函数（设置非阻塞/阻塞模式）
#include <chrono>   // 用于非阻塞模式下的延时
#include <thread>   // 用于 std::this_thread::sleep_for

// 设置为非阻塞模式
bool TcpClient::setNonBlocking() 
{
    if (!isConnectedStatus()) return false;
    
    // 获取当前 socket 标志
    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags == -1) 
    {
        std::cerr << "获取socket标志失败：" << strerror(errno) << std::endl;
        return false;
    }
    
    // 添加非阻塞标志
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) 
    {
        std::cerr << "设置非阻塞模式失败：" << strerror(errno) << std::endl;
        return false;
    }
    return true;
}

// 恢复阻塞+超时模式（默认3秒）
bool TcpClient::setBlockingWithTimeout(int timeoutSec) 
{
    if (!isConnectedStatus()) return false;
    
    // 清除非阻塞标志
    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags == -1) 
    {
        std::cerr << "获取socket标志失败：" << strerror(errno) << std::endl;
        return false;
    }
    if (fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK) == -1) 
    {
        std::cerr << "清除非阻塞模式失败：" << strerror(errno) << std::endl;
        return false;
    }
    
    // 重新设置超时
    struct timeval timeout;
    timeout.tv_sec = timeoutSec;
    timeout.tv_usec = 0;
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) 
    {
        std::cerr << "设置超时失败：" << strerror(errno) << std::endl;
        return false;
    }
    return true;
}